'''
抽取视图函数的代码  进行封装
1.把视图抽取到view模块里面
2.因为app注册蓝图对象的时候是导入的蓝图对象   而蓝图对象暂时接管的内容被我们封装了  所有需要在蓝图的模块里面导入我们封装的类视图   蓝图对象才会执行封装的内容
'''
from heima_toutiao.apps.home import home_bp

# 3.让蓝图暂时接管视图和路由
@home_bp.route('/home')
def home():
    return 'home'

# 使用FRF写首页类似类视图
from flask_restful import Resource
class HomeResource(Resource):
    def get(self):
        return {'msg':'home get'}


# 获取所有频道信息
'''
所有频道需求文档：   
                获取到频道推荐中的所有频道
前端：ajax请求

后端：
        获取所有频道接口文档
        请求方式：get
        请求路径：/app/v1_0/channels
        请求参数：无
        响应：channels:[{'id':##,'name':##}]
业务逻辑：
        前段发送ajax请求  获取到所有推荐的所有1.可见频道信息  2.按序号排序   返回的参数有id,name字段
        1.查询缓存数据---有   返回缓存数据
        2.没有缓存数据---查询数据库---把查询的数据存入缓存---返回数据 
'''
# 需要返回的数据--封装在field中
# #将频道列表对象转换
# from flask_restful import fields,marshal
# # 使用FRF将列表转换对象    返回 需要使用marshal方法,参数是data=查询的数据列表, fields=定义返回的字段和类型, envelope=信封 返回的key
# channels_fields = {
#     'id': fields.Integer,
#     'name': fields.String,
# }
class AllChannerlsResource(Resource):
    def get(self):
        # 封装查询数据
        from common.cache.channel import AllChannelCache
        # 封装的类方法  直接使用类名调用方法
        channels_list = AllChannelCache.get_data()
        return {'channels':channels_list}


# 获取用户关注频道
'''
需求：
    获取用户关注频道  ------根据用户id去查询缓存1.有返回2.没有--查询数据库 用户关注的频道1.没有被删除的2.排序按序号排序的所有频道信息----查询出来再保存缓存一份
                ----如果没有用户id 表示没有登录查询数据库  根据设置的没有登录用户查询缓存的key去查询缓存  有返回  没有查询数据库   1.频道条件是可见的2.频道条件默认是True 3.按序号排序---查询出来 以指定没有登录的默认用户的key保存缓存一份
前端：
    需要携带token发送ajax请求
后端：
    请求方式：get
    请求路径：/app/v1_0/user/channels
    请求参数：token 
    响应：'channels':[{'id':'这里的id不是查询的表的id而是频道的id'
                      'name':'这里的name也不是查询表的name而是频道的name'}]
    
'''

from flask import g
from flask import request
from common.models.news import UserChannel
from heima_toutiao import db
from common.cache.channel import UserChannelCache
class UserChannelsResource(Resource):
    def get(self):
        '''
        1.获取用户ID
        2.根据用户id进行判断
        3.登录用户进行数据查询
        4.没登录用户查询默认频道
        5.返回数据
        :return:
        '''
        # 1.获取用户ID
        user_id = g.user_id
        # 2.根据用户id进行判断
        if user_id:
            # 3.登录用户进行数据查询
            from common.cache.channel import UserChannelCache
            channels_list = UserChannelCache(user_id).get_data()
        else:
            # 4.没登录用户查询默认频道
            from common.cache.channel import DefaultUserChannelCache
            channels_list = DefaultUserChannelCache.get_data()
        # 因为前端页面 不管登录没登录都有一个 推荐频道 我们在返回数据的时候要加上


        # 5.返回数据


        return {'channels':channels_list}

    # 修改关注频道
    '''
    需求：
        修改关注频道   ---关注必须要用户登录
    前端：
        发送ajax请求   携带token  需要修改的频道 
    后端：
        接口文档
        请求方式：put
        请求参数：token 
        请求路径：app/v1_0/user/channels
        响应：
        {
        "message": "OK",
        "data": {
            "channels": [
                {
                    "id": 11,
                    "name": "html"
                },
            ]
        }
    }
    '''

    def put(self):
        # 1. 必须是登录用户才可以操作
        user_id = g.user_id
        # 2. 接收数据
        channels = request.json.get('channels')
        # [{id: 21, seq: 2}, {id: 2, seq: 3}, {id: 6, seq: 4}, {id: 4, seq: 5}]
        # 3. 验证数据[省略]
        # 4. 先把当前这个用户的所有关注频道删除,再新增前端提交的
        # UserChannel.query.filter(
        #     UserChannel.user_id == user_id
        # ).delete()
        #############使用逻辑删除在原有的数据基础上修改字段
        UserChannel.query.filter(UserChannel.user_id==user_id,UserChannel.is_deleted==False).update({'is_deleted':True})
        # for item in channels:
        #     # item = {id: 21, seq: 2}
        #     uc = UserChannel(
        #         user_id=user_id,
        #         channel_id=item.get('id'),
        #         sequence=item.get('seq')
        #     )
        ##############遍历请求中的频道参数
        for channel in channels:
            # 添加要更新的字段格式
            data = {"sequence": channel['seq'], "is_deleted": False}
            # 再根据用户和id和频道id去更新数据
            result = UserChannel.query.filter(
                UserChannel.user_id==user_id,
                UserChannel.channel_id==channel['id']
            ).update(data)
            #######执行删除频道数据 查询数据库更新data字段会返回结果是几行数据受到影响  如果是0就是数据没有变化  直接添加我们修改的字段修改数据库就可以了
            if result == 0:
                # 实例化用户关注频道模型类对象
                uc = UserChannel()
                # 修改字段
                uc.user_id = user_id
                uc.sequence = channel.get('seq')
                uc.channel_id = channel.get('id')
                db.session.add(uc)
        db.session.commit()
        # 5. 删除之前缓存的频道数据
        UserChannelCache(user_id).delete_data()
        # 6. 返回响应
        return {'channels': channels}

# 首页文章列表
'''
需求
    首页文章列表查询
前端:
    发送ajax请求
    用户点不同分类的时候携带分类id
后端：
    接口文档
    请求方式：get
    请求路径：/app/v1_*0/articles?channel_id=xxx&timestamp*=xxx&*with_top*=xxx
    请求参数：
    channel_id  查询参数
    token        请求头    不必传
    timestamp   时间戳     
    with_top    布尔类型
    响应：
    "pre_timestamp": 0,
    "results": [
        {
            "art_id": 140901,
            "title": "机器学习技术前沿与未来展望",
            "aut_id": 1,
            "pubdate": "2018-11-29T17:18:33",
            "aut_name": "黑马头条号",
            "comm_count": 0,
            "is_top":0,
            "cover":[{"type": 0, "images": []}]
        }
    ]
    
'''
from flask import abort
from common.models.news import Article
class IndexResouce(Resource):

    def get(self):
        # 1.接收参数
        channel_id=request.args.get('channel_id')
        if int(channel_id) == 0:
            channel_id = 1
        # 2.验证参数
        # channel = Channel.query.get(channel_id)
        # if channel is None:
        #     abort(404)
        # 3.根据参数查询数据
        articles=Article.query.filter(
            Article.channel_id == channel_id,
            # 查询文章必须是审核过的
            Article.status == Article.STATUS.APPROVED
        ).all()
        # 4.将对象转换为字典
        results=[]
        # flask-restful
        # 传统的方式
        for item in articles:
            results.append({
                "art_id": item.id,# 文章ID
                "title": item.title,# 文章标题
                "aut_id": item.user.id,# 作者id
                "pubdate": item.ctime.strftime('%Y-%m-%d %H:%M:%S'),#文章的创建时间---类型是datetime类型  需要转成字符串那类型
                "aut_name": item.user.name,# 作者名字
                "comm_count": item.comment_count,# 评论数
                "is_top": False,# 是否指定  默认否
                'cover': item.cover,# 文章封面
            })
        # 5.返回响应
        return {
            "pre_timestamp": 0,
            "results":results
        }

# 文章详情页面
"""

需求:
        实现详情页面的数据展示 

前端:
        发送一个ajax请求. 这个请求携带文章id

后端:
        GET app/v1_0/articles/<article_id>
        1. 获取文章id  ---查询缓存---有返回---没有--查数据库---保存
        2. 根据文章id查询文章信息
        3. 对象转字典
        4. 添加文章作者信息
        5. 初始化 是否关注, 是否点赞 是否收藏
        6. 返回响应

"""

from common.cache.article import ArticleDetailCache
class DetailResouce(Resource):

    def get(self,article_id):
        # 1. 获取文章id
        article_dict = ArticleDetailCache(article_id).get_data()

        if article_dict is None:
            abort(404)
        # 5. 初始化 是否关注, 是否点赞 是否收藏
        is_followed=False    #是否关注
        attitude = None      # 不喜欢0 喜欢1 无态度-1
        is_collected=False   #是否收藏
        # 用户登录的情况下可以对文章作者进行关注
        if g.user_id:
            from common.cache.user import UserFollowCache
            is_followed=UserFollowCache(g.user_id).exist(article_dict['aut_id']) # 文章作者的id---判断登录用户关注的作者id在不在redis数据库中的关注用户有序集合的key列表中
            # 如果在 更改初始化is_followed 为 关注
            # 不在返回False
            from common.cache.user import ArticleAttitudeCache
            attitude = ArticleAttitudeCache(g.user_id).getdate(article_id)
            # 判断用户是否 收藏文章
            from common.cache.user import CollectionCache
            is_collected = CollectionCache(g.user_id).exist(article_id)
            # 用户阅读自动增加缓存
            from common.cache.user import UserReadingHistoryCache
            UserReadingHistoryCache(g.user_id).save(article_id)

        article_dict['is_followed']=is_followed
        article_dict['attitude']=attitude
        article_dict['is_collected']=is_collected
        # 6. 返回响应
        return article_dict

# 点赞文章
'''
需求
    登录用户对文章的点赞
前端
    发送携带token 和 文章id的ajax请求
后端
    接口文档
    请求方式；post
    请求参数：token  请求头    target   请求体（文章id）
    请求路径：/article/likings
    响应：target
业务逻辑
    1.判断用户登录
    2.接受参数
    3.验证参数
    4.先查询数据库是否有存在的数据
    有  更新   没有  新增
    5.返回
'''
from heima_toutiao.apps.utils.decorators import login_required
from flask_restful.reqparse import RequestParser
from common.models.news import Attitude
class LikingResouce(Resource):
    method_decorators = [login_required]
    def post(self):
        # 1.判断用户登录
        user_id = g.user_id
        # 2.接受参数
        parser = RequestParser()
        parser.add_argument('target',type=int,required=True,location='json')
        # 3.验证参数
        args = parser.parse_args()
        target = args.target
        # 4.先查询数据库是否有存在的数据
        at = Attitude.query.filter(
            Attitude.user_id==user_id,
            Attitude.article_id==target
        ).first()

        # 有  更新   没有  新增
        if at is None:
            at = Attitude(
                user_id = user_id,
                article_id = target,
                attitude = Attitude.ATTITUDE.LIKING
            )
            db.session.add(at)
            db.session.commit()
        else:
            at.attitude=Attitude.ATTITUDE.LIKING
            db.session.commit()
        # 设置对文章点赞的态度
        from common.cache.user import ArticleAttitudeCache
        aac = ArticleAttitudeCache(user_id)
        aac.update(article_id=target,attitude=at.attitude)
        # 5.返回
        return {'target':target}
# 取消点赞
class UnLikingResouce(Resource):
    '''
    需求
        登录用户取消对文章的点赞
    前端
        发送携带token  target（路径传参） 的ajax请求
    后端
        接口文档
        请求方式：delete
        请求路径：/article/likings
        请求参数:token  target
        响应：target
    业务逻辑
        1. 必须是登录用户
        2. 接收参数
        3. 验证参数
        4. 更新状态
        5. 返回响应
    '''
    method_decorators = [login_required]
    def delete(self,target):
        # 1.必须是登录用户
        user_id = g.user_id
        # 2. 接收参数
        # 3. 验证参数
        # 4. 更新状态
        at = Attitude.query.filter(
            Attitude.user_id==user_id,
            Attitude.article_id==target
        ).first()
        if at:
            #如果有数据   设置为None  没态度
            at.attitude=None
            db.session.commit()
            # 设置对文章的态度
            from common.cache.user import ArticleAttitudeCache
            aac = ArticleAttitudeCache(g.user_id)
            aac.update(article_id=target,attitude=at.attitude)

            # 5. 返回响应
            return {'target':target}
        else:
            abort(400)
# 不喜欢
class DisLikingResouce(Resource):
    '''
    需求
        登录用户对文章不喜欢
    前端
        发送携带token 和 target的ajax
    后端
        接口文档
        请求方式：post
        请求参数：token  target
        请求路径：/article/dislikes
        响应：target
    '''
    # 必须登录
    method_decorators = [login_required]
    def post(self):
        # 1.接受参数
        parser = RequestParser()
        parser.add_argument(
            'target',
            type=int,
            required=True,
            location='json'
        )
        # 2.校验参数
        args = parser.parse_args()
        target = args.target
        # 3.验证数据库是否有存在数据
        at = Attitude.query.filter(
            Attitude.user_id==g.user_id,
            Attitude.article_id==target
        ).first()
        # 4.如果有  更新状态为不喜欢
        if at:
            at.attitude=Attitude.ATTITUDE.DISLIKE
            db.session.commit()
            # 设置对文章点赞的态度
            from common.cache.user import ArticleAttitudeCache
            aac = ArticleAttitudeCache(g.user_id)
            aac.update(article_id=target,attitude=at.attitude)
            return {'target':target}

        else:
            abort(400)
# 取消不喜欢
class UnDisLikingResouce(Resource):
    method_decorators = [login_required]
    def delete(self,target):
        # 必须登录
        # 参数是路径传参已经校验过了
        # 根据参数查询数据库---有  更新   没有abort400
        at = Attitude.query.filter(
            Attitude.user_id==g.user_id,
            Attitude.article_id==target
        ).first()
        if at:
            at.attitude=None
            db.session.commit()
            # 设置对文章的态度
            from common.cache.user import ArticleAttitudeCache
            aac = ArticleAttitudeCache(g.user_id)
            aac.update(article_id=target,attitude=at.attitude)
            return {'target':target}
        else:
            abort(400)
from common.models.news import Collection
# 收藏文章
from common.cache.user import UserCollectionCache
class CollectionResource(Resource):
    '''
    收藏文章接口文档
    请求方式：post
    请求参数：token target
    请求路径：/article/collections
    响应：target
    '''
    method_decorators = [login_required]
    def post(self):
        '''
        1.接受参数
        2.校验参数
        3.更新数据
        4.返回
        :return:
        '''
        # 1.接受参数
        parser = RequestParser()
        parser.add_argument('target',type=int,required=True,location='json')
        # 2.校验参数
        args = parser.parse_args()
        target = args.target
        # 3.更新数据---1.查询数据库是否有该用户收藏的这篇用户的数据2.有--更新  没有---添加
        try:
            collection = Collection(user_id=g.user_id, article_id=target)
            db.session.add(collection)
            db.session.commit()
        except Exception as e:
            # 在添加数据库的时候 如果有一条数据的话  插入会保存  需要事务执行暴力回归
            db.session.rollback()
            Collection.query.filter_by(user_id=g.user_id, article_id=target, is_deleted=True).update({'is_deleted': False})
            db.session.commit()
            # 缓存收藏数据
            from common.cache.user import CollectionCache
            CollectionCache(g.user_id).update(article_id=target,action=1)
        # 4.返回
        return {'target':target}
    def get(self):
        '''
        需求
            用户收藏列表
        前端
            发送携带token的ajax请求  page  per_page 不是必传
        后端
            接口文档
            请求方式：get
            请求路径：article/collections
            请求参数：token必传 page  per_page 不是必传
            响应：
            "page": 1,
            "per_page": 10,
            "total_count": 100,  数量
            "results": [
                {
                    "art_id": 108, 文章id
                    "title":"Python如何学好" 文章标题
                    "aut_id": 1155989075455377414,评论id
                    "aut_name": "18310820688",用户昵称
                    "aut_photo": "",用户头像
                    "pubdate": "2019-08-07T08:53:01",创建时间
                    "cover": "封面",
                      "type": 0,
                      "images":[]
                      "is_liking": 0 当前用户是否点赞
                }
            ]
            业务逻辑
                1.必须是登录用户
                2.获取分页参数----参数是通过查询参数获取---查询参数获取到的数据为str  需要转换int
                page   int页数 默认是1
                per_page  int 每页数量
                3.获取收藏的数据---缓存类
                    需要定义一个收藏缓存类的  获取方法
                4.根据文章id查询文章详细信息---文章详情页面是做了缓存的---使用文章详情缓存类查询详细信息
                5.响应
        :return:
        '''
        # 1.必须是登录用户
        user_id = g.user_id
        # 2.获取分页参数----参数是通过查询参数获取---查询参数获取到的数据为str  需要转换int
        # page   int页数 默认是1
        page = request.args.get('page',1)
        # per_page  int 每页数量
        per_page = request.args.get('per_page',10)
        if page:
            page=int(page)
        if per_page:
            per_page=int(per_page)
        # 3.获取收藏的数据---缓存类
        #     需要定义一个收藏缓存类的  获取方法
        art_ids = UserCollectionCache(user_id).get_ids(page,per_page)
        # 4.根据文章id查询文章详细信息---文章详情页面是做了缓存的---使用文章详情缓存类查询详细信息
        results = []
        for art_id in art_ids:
            article = ArticleDetailCache(article_id=art_id).get_data()
            results.append(article)
        # 用户收藏总数
        count=UserCollectionCache(user_id).get_total()
        # 5.响应
        return {
            'page':page,
            'per_page':per_page,
            'total_count':count,
            'results':results
        }

# 取消收藏
class UnCollectionResource(Resource):
    '''
    收藏文章接口文档
    请求方式：delete
    请求参数：token target
    请求路径：/article/collections/<int:target>
    响应：target
    '''
    method_decorators = [login_required]
    def delete(self,target):
        '''
        请求方式：delete
        请求参数：token   target
        请求路径：/article/collections/<int:target>
        响应：target
        :param target:
        :return:
        '''
        # 1.接受参数
        # 2.校验参数
        # 3.更新数据---逻辑删除
        Collection.query.filter(
            Collection.user_id==g.user_id,
            Collection.article_id==target,
            Collection.is_deleted==False
        ).update({'is_deleted':True})
        db.session.commit()
        # 缓存收藏数据
        from common.cache.user import CollectionCache
        CollectionCache(g.user_id).update(article_id=target, action=0)
        # 4.返回
        return {'target':target}
# 评论
from common.models.news import Comment
class CommentResouce(Resource):
    method_decorators = [login_required]
    def post(self):
        '''
        需求
            登录用户才能发布评论
        前端
            输入评论信息.回车发表
            前端发送ajax请求  携带token 评论信息在请求的body中和文章id
        后端
            接口文档
            请求方式：post
            请求路径：comments
            请求参数：token   target文章id  content评论内容
            响应：com_id评论id  target文章id
        业务逻辑
            1.接受参数
            2.校验参数
            3.数据入库
            4.响应
        :return:
        '''
        # 1.接受参数
        parser = RequestParser()
        parser.add_argument(
            'target',
            required=True
        )
        parser.add_argument(
            'content',
            required=True
        )
        # 加入判断评论还是回复评论的参数   如果是对评论评论的时候 这个参数的值就是文章id
        parser.add_argument(
            'art_id',
            type=int,
            required=False,
            location='json'
        )
        # 2.校验参数
        args = parser.parse_args()
        target = args.get('target')
        content = args.get('content')
        art_id = args.get('art_id')
        # 3.数据入库
        if art_id is None:
            # 对文章评论
            cm = Comment(
                user_id=g.user_id,
                article_id=target,
                content=content
            )
        else:
            # 添加记录评论信息写到redis缓存中
            from common.cache.statistic import CountCommentReply
            CountCommentReply.incr(args.get('target'))
            # 对评论评论
            cm = Comment(
                user_id=g.user_id,
                article_id=art_id,
                content=content,
                parent_id=target

            )
        db.session.add(cm)
        db.session.commit()
        # 4.响应
        return {'target':target,'comm_id':cm.id}
    # 评论/回复评论列表
    def get(self):
        '''
        需求
            查询出所有评论
        前端
            发送ajax请求---查询字符串type  a表示文章评论 c表示回复评论
        后端
            接口文档
            请求方式：get
            请求路径：comments
            请求参数：type   source offset limit
            响应：
            "total_count": 1,
            "end_id": 108,  # 最后一条评论的id, 前端用于判断是否剩余评论, 无值返回None
            "last_id": 108,  # 本次请求最后一条评论的id, 作为下次请求的offset, 无值返回None
            "results": [
                {
                    "com_id": 108,
                    "aut_id": 1155989075455377414,
                    "aut_name": "18310820688",
                    "aut_photo": "",
                    "pubdate": "2019-08-07T08:53:01",
                    "content": "你写的真好",
                   "is_top": 0,
                   "is_liking": 0
                   }
                ]
            业务逻辑
                1.接受参数
                2.校验参数
                3.业务逻辑 ---判断评论类型   如果是a表示文章  如果是b表示评论
                4.返回
        :return:
        '''
        # 1.接受参数
        parser = RequestParser()
        parser.add_argument('type', type=str, required=True, location='args', help='评论类型')
        parser.add_argument('source', type=int, required=True, location='args', help='文章id或评论id')
        # 2.校验参数
        args = parser.parse_args()
        type = args.get('type')
        source = args.get('source')
        # 3.业务逻辑
        # 判断评论类型
        if type == 'a':
            # 文章评论 ---那么source就是文章id
            article_id = args.source
            # 根据文章id   和分类ID为None去查询数据库（而且该评论还是要审核通过的）----按创建时间降序来排序
            comments = Comment.query.filter(
                Comment.article_id == article_id,
                Comment.status == Comment.STATUS.APPROVED,
                Comment.parent_id == None
            ).order_by(Comment.ctime.desc()).all()
        else:
            # type ==c 的时候是评论类型
            comments = Comment.query.filter(
                Comment.parent_id == source,
                Comment.status == Comment.STATUS.APPROVED
            ).order_by(Comment.ctime.desc()).all()
        # 将对象列表转换成字典列表
        results = []
        # 添加是否点赞评论判断
        from common.cache.user import UserCommitLikingCache
        # 添加查询回复数量
        from common.cache.statistic import CountCommentReply
        for comment in comments:
            results.append({
                'com_id': comment.id,
                'aut_id': comment.user.id,
                'aut_name': comment.user.name,
                'aut_photo': comment.user.profile_photo,
                'pubdate': comment.ctime.strftime('%Y-%m-%d %H:%M:%S'),
                'content': comment.content,
                'is_top': comment.is_top,
                'is_liking': UserCommitLikingCache(g.user_id).exist(comment.id),#UserCommitLikingCache(g.user_id).exist(comment.id)
                'reply_count': CountCommentReply.get(comment.id)
            })
        # 4.返回
        return {
            "total_count": len(comments),
            "end_id": 0,  # 最后一条评论的id, 前端用于判断是否剩余评论, 无值返回None
            "last_id": 0,  # 本次请求最后一条评论的id, 作为下次请求的offset, 无值返回None
            "results": results
        }
from common.models.news import CommentLiking
# 评论或回复评论点赞
class CommentLikingResource(Resource):
    '''
    需求
        登录用户对评论  或者回复评论的评论进行点赞
    前端
        发送ajax请求携带token和评论id
    后端
        接口文档
        请求方式：post
        请求路径：comment/likings
        请求参数：token   target
        响应：target
    业务逻辑
        1.获取参数
        2.解析校验参数
        3.根据用户id和评论id拿到数据  进行数据更新
        4.返回
    '''
    method_decorators = [login_required]
    def post(self):
        # 1.获取参数
        user_id=g.user_id
        # 2.解析校验参数
        comm_id = request.json.get('target')
        # 3.根据用户id和评论id拿到数据  进行数据更新
        cl = CommentLiking.query.filter(
            CommentLiking.user_id==user_id,
            CommentLiking.comment_id==comm_id
        ).first()
        if cl:
            cl.is_deleted=False
            db.session.commit()
        else:
            cl = CommentLiking(
                user_id=user_id,
                comment_id=comm_id
            )
            db.session.add(cl)
            db.session.commit()
        # 点赞之后增加缓存, 调用类方法
        from common.cache.user import UserCommitLikingCache
        UserCommitLikingCache(g.user_id).update()

        # 4.返回
        return {'target':comm_id}
class UnCommentLikingResource(Resource):
    method_decorators = [login_required]
    def delete(self,target):
        '''
        1.获取参数
        2.解析参数
        3.更新数据
        4.清理缓存
        :return:
        '''
        user_id = g.user_id
        CommentLiking.query.filter(
            CommentLiking.user_id==user_id,
            CommentLiking.comment_id==target,
            CommentLiking.is_deleted==False
        ).update({'is_deleted':True})
        db.session.commit()
        # 清楚缓存
        from common.cache.user import UserCommitLikingCache
        UserCommitLikingCache(g.user_id).clear()
        return {'target':target}





